package org.budo.time;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * @author lmw
 */
public interface TimePoint {
    Date getDate();

    /**
     * 一定返回正数
     */
    TimeSpan between(TimePoint that);

    /**
     * 一定返回正数
     */
    TimeSpan between(Long that);

    /**
     * 一定会返回正数
     */
    TimeSpan between(Date that);

    /**
     * 可能返回负数
     * 
     * @see org.budo.time.TimeSpan#abs()
     */
    TimeSpan betwixt(TimePoint that);

    TimeSpan betwixt(Date that);

    TimeSpan betwixt(Long that);

    /**
     * 三者中有空值时返回false 与两端相等返回true
     */
    Boolean isBetween(TimePoint min, TimePoint max);

    Boolean isBetween(Date min, Date max);

    /**
     * 三者中有空值时返回false 与两端相等返回false
     */
    Boolean isBetwixt(TimePoint min, TimePoint max);

    Boolean isBetwixt(Date min, Date max);

    /**
     * 二者中有空值时返回false
     */
    Boolean isAfter(TimePoint that);

    Boolean isAfter(Date that);

    /**
     * 二者中有空值时返回false
     */
    Boolean isBefore(TimePoint that);

    Boolean isBefore(Date that);

    /**
     * 二者中有空值时返回false
     */
    Boolean isEqual(TimePoint that);

    Boolean isEqual(Date that);

    /**
     * 是周六
     */
    Boolean isSaturday();

    /**
     * 是周日
     */
    Boolean isSunday();

    /**
     * 整点; 将分秒毫秒设置为0
     */
    TimePoint sharp();

    /**
     * 将时间部分设置为 0:0:0.0 后返回
     */
    TimePoint datePart();

    /**
     * 获取当前时间是哪一年
     */
    Integer getYear();

    Integer getMonth();

    /**
     * DAY_OF_MONTH
     */
    Integer getDay();

    Integer getDayOfWeek();

    Integer getHour();

    Integer getMinute();

    Integer getSecond();

    Integer getMilliSecond();

    /**
     * 当前时间减去指定时间
     */
    TimePoint minusYear(Number year);

    TimePoint minusMonth(Number month);

    TimePoint minusDay(Number day);

    TimePoint minusHour(Number hour);

    TimePoint minusMinute(Number minute);

    TimePoint minusSecond(Number second);

    TimePoint minusMilliSecond(Number milliSecond);

    /**
     * 当前时间加上指定时间
     */
    TimePoint plusYear(Number year);

    TimePoint plusMonth(Number month);

    TimePoint plusDay(Number day);

    TimePoint plusHour(Number hour);

    TimePoint plusMinute(Number minute);

    TimePoint plusSecond(Number second);

    TimePoint plusMilliSecond(Number milliSecond);

    /**
     * 传入值
     */
    TimePoint setYear(Number year);

    TimePoint withYear(Number year);

    /**
     * 请留意 +1 问题
     */
    TimePoint setMonth(Number month);

    /**
     * 请留意 +1 问题
     */
    TimePoint withMonth(Number year);

    /**
     * 设置 DAY_OF_MONTH
     */
    TimePoint setDay(Number day);

    TimePoint withDay(Number day);

    TimePoint setHour(Number hour);

    TimePoint withHour(Number hour);

    TimePoint setMinute(Number minute);

    TimePoint withMinute(Number minute);

    TimePoint setSecond(Number second);

    TimePoint withSecond(Number second);

    TimePoint setMilliSecond(Number milliSecond);

    TimePoint withMilliSecond(Number milliSecond);

    /**
     * 更新日期为本月最后一天
     */
    TimePoint setDayMax();

    /**
     * 设置日期部分
     * 
     * @param year
     * @param month 一月是0，二月是1
     * @param day
     */
    TimePoint setDate(Number year, Number month, Number day);

    TimePoint setTime(Number hour, Number minute, Number second);

    /**
     * 设置时间部分
     */
    TimePoint setTime(Number hour, Number minute, Number second, Number milliSecond);

    /**
     * 更新时间为 23, 59, 59, 999
     */
    TimePoint setTimeMax();

    /**
     * 将日期部分设置为 1970-0-1，即 70年1月1号 后返回
     */
    TimePoint timePart();

    Calendar toCalendar();

    /**
     * 返回 java.util.Date 类型
     */
    Date toDate();

    java.sql.Date toSqlDate();

    java.sql.Time toSqlTime();

    String toString(TimeFormat format);

    Timestamp toTimestamp();

    /**
     * Ret@Override
    urns the number of milliseconds since January 1, 1970, 00:00:00 GMT
     */
    Long toMilliSeconds();

    /**
     * Retu@Override
    rns the number of seconds since 1970-1-1, 00:00:00 GMT
     */
    Long toSeconds();

    /**
     * yyyy-MM-dd yyyy-MM-dd HH:mm:ss.SSS yyyyMMdd.HHmmss.SSS
     */
    String toString(String pattern);

    String toString(String pattern, Locale locale);

    Boolean isBeforeNow();

    LocalDateTime toLocalDateTime();

    LocalDate toLocalDate();

    LocalTime toLocalTime();

    Instant toInstant();

    TimePoint startOfMonth();

    TimePoint startOfWeek();

    TimePoint startOfYear();

    TimePoint startOfDay();

    TimePoint startOfHour();

    TimePoint timeFieldSet(Integer field, Number value);

    TimePoint timeFieldPlus(Integer field, Number amount);

    /**
     * 向上取整
     */
    TimePoint ceilSecond();

    /**
     * 四舍五入
     */
    TimePoint roundSecond();

    /**
     * 向下取整
     */
    TimePoint floorSecond();

    /**
     * 向上取整
     */
    TimePoint ceilMilliSecond();

    /**
     * 四舍五入
     */
    TimePoint roundMilliSecond();

    /**
     * 向下取整
     */
    TimePoint floorMilliSecond();

    TimeSpan betweenNow();

    <T> T toType(Class<T> type);

    TimePoint or(TimePoint defaultValue);

    TimePoint orNow();

    TimePoint setDayOfWeek(Number dayOfWeek);

    TimePoint setWeekOfMonth(Number weekOfMonth);

    /**
     * DAY_OF_MONTH 返回当月最大日期 30/31/29/28
     */
    Integer getDayMax();

    Integer getWeekOfMonth();

    /**
     * 二者中有空值时返回false
     */
    Boolean isNotBefore(TimePoint that);

    /**
     * 二者中有空值时返回false
     */
    Boolean isNotAfter(TimePoint that);

    /**
     * 二者中有空值时返回false
     */
    Boolean isNotEqual(TimePoint that);

    /**
     * 三者中有空值时返回false 与两端相等返回false
     */
    Boolean isNotBetween(TimePoint min, TimePoint max);

    /**
     * 三者中有空值时返回false 与两端相等返回true
     */
    Boolean isNotBetwixt(TimePoint min, TimePoint max);

    /**
     * @param that 应该是偏后的时间,否则会会返回负数
     */
    TimeSpan until(TimePoint that);

    /**
     * @param that 应该是偏后的时间,否则会会返回负数
     */
    TimeSpan until(Date that);

    String toString(DateFormat dateFormat);
}